%changes for SOS Release 3.2 by M. Ranft marked with "29.10.91mr"
\section{The SOS Schema Language}
\label{sec:The SOS Schema Language}

This section explains the syntax and semantics of the schema
language.
The syntax is presented using extended BNF.
Terminal symbols are written in boldface.
The constructs P+, P$\star$, [P], (P1 // P2), [P1 // P2] stand for
one or more, zero or more, zero or one occurrence of P, one or more
occurrences of P1 separated by P2, and zero or more occurrences of P1
separated by P2, respectively.
Symbol prefixes written in italics refer to the semantics of the
symbol; they are meaningless for the syntactic definition. In
particular, note the difference between a ``{\it type-}name'' which
denotes the syntactic category ``name'' and tells that the name must
refer to a type, and ``type-name'' which is a non-terminal symbol
that, besides ``name'', includes ``generic-instantiation''.

% ---------
\subsection{Lexical Items}

The basic items of the schema language are names, keywords, numbers,
and special symbols. A name may consist of letters, digits, and
underscores, starting with a letter or underscore.
SOS and other systems tend to generate names that start with an underscore, so 
it is not safe to use such names.

A keyword is a name that is reserved for a special purpose. It must
not be used as a name.
The following names are reserved for use as keywords: {\tt abstract},
{\tt class}, {\tt definite}, {\tt enum}, {\tt extern},
{\tt friend}, {\tt local}, {\tt operator},
{\tt private}, {\tt protected}, {\tt public}, {\tt schema},
{\tt static}, {\tt typedef}, {\tt union}, and {\tt with}.

A number is a sequence of digits.

Comments either start with the symbol ``{\bf //}'' and end with the
line, or start with the symbol ``{\bf /*}'' and end at the nearest
following symbol ``{\bf */}''.
Comment, tabulator, blank, newline, and formfeed act as white space.

% ---------
\subsection{Schemas and Types}
\begin{Grammar}
\>schema ::=\\
\>\>imports\\
\>\>{\bf schema} {\it schema-}name\\
\>\>{\bf \{} type-declaration$\star$\\
\>\>{\bf \}} [ {\bf ;} ]\\
\end{Grammar}
\begin{Grammar}
\>imports ::=\\
\>\>[ schema-imports ]  [ {\bf with extern ;} ]\\
\>schema-imports ::=\\
\>\>{\bf with} ( {\it schema-}name // {\bf ,} ) [ {\bf ;} ]\\
\end{Grammar}

A {\it schema} declares a set of types.
Type declarations from one schema may be used in other schemas by
naming the schema in the ``schema-imports'' clause.
Schema import is transitive: all schemas imported by an imported 
schema will also be available in the importing schema.
The type declarations of all imported schemas together with their
imported schemas and so on, together with the current schema
constitute a single name space, where no name clashes are allowed.
Schema modules may be compiled separately.
The schema {\tt knl} that declares some kernel types is automatically
imported.
Other types, including the remaining predefined types introduced in
Section~\ref{sec:The SOS Environment}, must be imported explicitly.

The schema names {\tt knl}, {\tt agg}, {\tt mta}, {\tt dir},
and {\tt cci}, are reserved for the kernel schema, the schema
providing the aggregate data types, the meta schema, the schema
providing data types for directory structures, and the
C++-implementation schema used by the C++ interface builder.

The declaration ``{\tt with extern}'' provides a way to add
declarations defined outside the schema language to the schema
interface generated by the interface builder of a programming
language.
The placement and form of such external declarations depends on the
interface language and the corresponding interface builder. 

% ---------
\subsection{Type Declarations}
\label{sec:Type Declarations}

A ``type-declaration'' introduces a name for a type.
That type can be used in the current schema module after its
declaration and in all schema modules that import this module.
Class types can additionally be used before their declarations
provided that these declarations follow in the same schema module.
% 29.10.91mr
\footnote{The only exception from this is the usage of a class type as the
          name of a superclass in the declaration of a {\it derived class}
          (see Section~\ref{sec:Derived Classes}).},
% end 29.10.91mr
A ``type-declaration'' may declare an external type, an enumeration
type, a union type, or a class type.
It may also just give a new name to some already declared type.


\begin{Grammar}
\>type-declaration ::=\\
\>\>extern-declaration $|$ enumeration-declaration $|$\\
\>\>typedef-declaration $|$\\
\>\>union-declaration $|$ class-declaration\\
\\
\>extern-declaration ::=
  {\bf extern} {\it type-}name [ {\bf (} number {\bf )} ] {\bf ;}\\
\\
\>enumeration-declaration ::=
  {\bf enum} {\it type-}name {\bf \{}
             ( {\it literal-}name // {\bf ,} ) {\bf \}} [ {\bf ;} ]\\
\end{Grammar}
\begin{Grammar}
\>typedef-declaration ::=\\
\>\>{\bf typedef} type-name {\it type-}name {\bf ;} $|$\\
\>\>{\bf typedef} generic-instantiation {\bf ;}\\
\\
\>type-name ::= {\it type-}name $|$ generic-instantiation\\
\end{Grammar}

An {\it external type} is a type that is defined outside the schema
language using some programming language.
There is a fixed size that is reserved for values of external types,
whose size may optionally be specified by a number (in bytes); the default
size is 4 bytes; the maximum size is 8 bytes.
External types may be useful to integrate existing programs with SOS.
In all other cases, it is recommended to only use the modeling
facilities of the schema language for the definition of types.
Some external types are defined in the kernel, like {\tt sos\_Int},
{\tt sos\_Bool}, or {\tt sos\_Char}
(see Section~\ref{sec:The SOS Environment}).

An ``extern-declaration'' causes an implicit {\tt with extern}
declaration for the given schema (see above).

An {\it enumeration type} is defined by enumerating its literals in
an ``enumeration-declaration''.
These literals are the only values of the enumeration type.

The first form of a ``typedef-declaration'' introduces a new name
for the type denoted by the ``type-name'' (both names refer to the
same type); the second form declares a generic instantiation
(see Section~\ref{sec:Generic Class Types}).

{\bf Example:}
\begin{verbatim}
extern Register;
enum Register_status {REG_FREE, REG_OCCUPIED, REG_LOCKED};
typedef Mapping<Register, Register_status> Register_map;
\end{verbatim}
The type {\tt Register\_map} represents the instantiation of a
generic class {\tt Mapping} (see below).

$\Box$

%----------
\subsection{Union Types}
\begin{Grammar}
\>union-declaration ::=
  {\bf union} {\it type-}name
  {\bf \{} ( type-name // {\bf ,} ) {\bf \}} [ {\bf ;} ]
\end{Grammar}

A union type acts like a superclass of the specified types, except
that it cannot define methods.
A union type may, for example, be used as a formal parameter type,
where the actual parameter may be of any of its united types.
The transitive closure of the relation between union types and their
united types must be acyclic.

% ---------
\pagebreak[4]
\subsection{Class Types}
\label{sec:Class Types}
\begin{Grammar}
\>class-declaration ::=\\
\>\>{\bf class} {\it type-}name class-body  [ {\bf ;} ]\\
\\
\>class-body ::=\\
\>\>[ {\bf $<$} (generic-parameter-specification // {\bf ,})
      {\bf $>$} ]\\
\>\>[ {\it create}-parameters ]\\
\>\>[ {\bf :} super-classes ]\\
\>\>{\bf \{} (
    \>~~friend-specification\\
\>\>\>$|$ method-kind-specification\\
\>\>\>$|$ method-declaration )$\star$\\
\>\>{\bf \}}\\
\\
\>generic-parameter-specification ::=\\
\>\>{\it type-}name [ {\bf :} {\it superclass-}type-name ]\\
\\
\>super-classes ::=\\
\>\>( class-initialization // {\bf ,} )\\
\>class-initialization ::=\\
\>\>{\it class-}type-name [ {\bf (} [ expression // {\bf ,} ] {\bf )} ]\\
\\
\>friend-specification ::=\\
\>\>{\bf friend class} {\it class-}type-name {\bf ;}\\
\\
\>method-kind-specification ::=\\
\>\>method-kind-specifier
    [ {\bf ,} method-kind-specifier {\bf set} ] {\bf :}\\
\>method-kind-specifier ::=\\
\>\>{\bf public} $|$ {\bf protected} $|$ {\bf private}\\
\\
\>method-declaration ::=\\
\>\>function-method $|$ component-declaration\\
\end{Grammar}

A class type declaration mainly consists of the declaration of the
methods that are associated with the class.
{\it Methods} can be implicitly declared component methods (methods
predefined for components, i.e. slots or attributes)
or explicitly declared function methods having parameters and a
result.
The specification of create parameters and class initializations is
explained in Section~\ref{sec:Object Creation}.

\pagebreak[4]
{\bf Example:}\label{date-exa}
\begin{verbatim}
class Date
{     
public, private set:
      sos_Int  month, day, year;
public:
      void  set_date(sos_Int, sos_Int, sos_Int);
      void  print_date();
      ...
};
\end{verbatim}

An example of a class {\tt Date} with components {\tt month}, {\tt day} and
{\tt year} and user-defined methods {\tt set\_date} and 
{\tt print\_date}.

$\Box$

%-------------
\subsubsection{Information Hiding}
\label{sec:Information Hiding}

Methods and components may be declared in public, protected, or
private parts; a part is started with the corresponding keyword.
Optionally, a part may be started with the declaration of a separate
access right for the methods generated to set components to a new
value (see below), by adding the word ``{\bf set}'' to a 
``method-kind-specifier''.
The first part of a class type is implicitly private.
Private methods can be accessed only in (the implementation of)
methods of the given class, protected methods are, in addition,
accessible in all derived classes, and the access to public methods
is not restricted. 

A friend specification enables the denoted type, which must be a
class type, to access private and protected methods (including
inherited protected methods) of the class type in which the friend
specification occurs.

The way in which these information hiding constraints are enforced
depends on the host language.

%-------------
\subsubsection{Components and Component Methods}
\label{sec:Components and Component Methods}

\begin{Grammar}
\>component-declaration ::=\\
\>\>static-component $|$ non-static-component\\
\\
\>static-component ::=\\
\>\>{\bf static} type-name ( {\it component-}name // {\bf ,} )
    {\bf ;}\\
\\
\>non-static-component ::=\\
\>\>component-kind type-name ( component-specification // {\bf ,} )
    {\bf ;}\\
\>component-specification ::=\\
\>\>{\it component-}name [ {\bf =} expression ]\\
\>component-kind ::=\\
\>\>[ {\bf definite} ]  [ {\bf local} $|$ {\bf !} ]\\
\end{Grammar}
Inspection and update of components is done via implicitly declared
function methods. A component declared by
\begin{verbatim}
   T c;
\end{verbatim}
implicitly declares the component methods
\begin{verbatim}
   void  set_c (T);
   T     get_c ();
\end{verbatim}
which set and get the corresponding component value.
{\tt c} will hold the identity of the given object and can thus be
considered as a pointer to that object.

A ``static-component'' belongs to the class itself and not to any
instance of the class.
Therefore, the methods to access this component will be generated as
static methods, too.

The specifier {\tt definite} takes effect on
component methods as described in the following section on function
methods: a {\it definite} method must not be redefined in a subclass.

{\it Local} components may only refer to objects within the same
container as the object the component belongs to.

It is possible to declare components whose {\tt get} and {\tt set}
methods have different access conditions. In the example on 
page~\pageref{date-exa} the {\tt get} methods of all components are 
defined to be public, whereas the {\tt set} methods are private.

A ``non-static-component'' can be initialized by giving an
appropriate initialization expression. 
The initialization of these so-called
{\it init-components} is done as part of the creation of an object
(see Section~\ref{sec:Object Creation}).

We distinguish the {\it identity} and the {\it value} of an SOS
{\it object}.
The value of an object can be modified in time whereas its identity
is immutable.
When we talk about objects we usually mean their identity.
The objects (referred to by) {\tt A} and {\tt B} are identical,
if {\tt A} denotes the same object as {\tt B}, whereas {\tt A} and
{\tt B} are said to be {\it equal\/} if they have the same value.
The value of an object is determined by its components%
\footnote{What makes up the value of an object may be redefined by
          a schema implementor by explicitly defining otherwise
          generated function methods that assign values to an object
          and that check for equality of values 
          (see Section~\ref{sec:Comparing Objects}).}.
Depending on whether a component of an object is a {\it value
component} (i.e. a component declared with the value specifier {\tt !})
or not, the value of the object is made up from the value or the
identity of the component, respectively.

Objects of scalar types are conceptually created together with the
type.
When the type {\tt sos\_Int} is declared, all integer objects exist
from then on; they are constant objects, that means their value
cannot change.
Identity and equality are equivalent for scalar objects/values.
A component with a scalar type must not be a value component.

Value components are considered to be a dependent part of an
object which is therefore called their master object.
An object can only be the value component of one master object.
The connection between a value component and its master object can
not be loosened any more once it is established, i.e. neither can
another object be associated as that value component nor can the
value component be decoupled from its master object.
Value components are initialized to the special value
{\tt NO\_OBJECT} (see Section~\ref{sec:Names and Expressions})
at object creation.
For value components, the function to set this component may
be used only once to establish the connection between an object and
its master object.
A value component is implicitly defined as {\bf local}.

Several predefined function methods
(see Section~\ref{sec:Predefined Methods}) are transitively applied
to the value components of an object.
For example, the destruction of an object automatically destroys its
value components; equality checks for equality of the value
components, and so on.

{\bf Example:}

The declaration of class {\tt Document} illustrates the use of
value components.

\begin{verbatim}
class Person { ... };

class Date { ... };
class Document
{
  protected: 
      static void local_initialize (Document);

  public:
       Set<Person>  authors;
       Person       owner;
      !Date         creation_date; 
      !Date         modification_date;
};
\end{verbatim}

The components {\tt creation\_date} and {\tt modification\_date} are
value components of the class {\tt Document}.
Thus, two instances of class {\tt Date} indicating the date of
creation and the last modification date of a document can once be
connected to an instance of class {\tt Document}.
In this example this would be done during the initialization of
instances of class {\tt Document}
(cf. Section~\ref{sec:Object Creation}).
These instances of class {\tt Date} will be destroyed together with
the destruction of the instance of class {\tt Document}.
Note, that only the connections are fixed but not the states of the 
{\tt Date} instances.

$\Box$

%-------------
\subsubsection{Function Methods}
\label{sec:Function Methods}

\begin{Grammar}
\>function-method ::=\\
\>\>[ function-kind ]
    {\it result-}type-name function-name parameters {\bf ;}\\
\>function-kind ::=\\
\>\>{\bf static} $|$ {\bf definite} $|$ {\bf abstract}
\\
\>function-name ::=\\
\>\>{\it function}-name $|$ {\bf operator} operator-symbol\\
\\
\>operator-symbol ::=\\
\>\>{\tt * $|$ /  $|$ \% $|$ +  $|$ -   $|$ << $|$ >> $|$ <    $|$ >
    $|$ == $|$ != $|$ <= $|$ >= $|$ \^\ $|$ \& $|$ |  $|$ \&\& $|$}\\
\>\>{\tt || $|$ =  $|$ +=  $|$ -=  $|$ *= $|$ /= $|$ \%= $|$ \^{ }=
    $|$ \&= $|$ |= $|$ >>= $|$ <<= $|$ () $|$ []}\\
\\
\>parameters ::= {\bf (} [ parameter // {\bf ,} ] {\bf )}\\
\>parameter ::=\\
\>\>type-name [ {\bf \&} ]
    [ {\it parameter-}name ] [ {\bf =} expression ]\\
\end{Grammar}

\label{Function Methods-after Grammar}
A function may be {\it static} or {\it non-static}.
A static function belongs to the class itself and is not applied to
an object of the class.
Non-static methods are applied to objects of the class.
All non-static function methods are {\it virtual} in the sense that a
redefinition of a method in a subclass replaces the original method
for all objects that are created as instances of the subclass.

A function method that is declared to be {\it definite} must not be
redefined in a subclass.

A class containing {\it abstract} function methods is called an
{\it abstract class}.
No objects of an abstract class can be created.
Abstract function methods are not inherited, they must be
(re-)defined in all subclasses, possibly again as abstract function
methods.
An error is raised if a not redefined abstract function method is 
executed.

Parameters are by default passed by value.
An ampersand ({\tt \&}) after a parameter type name indicates that 
the parameter is passed by reference.

A user may also explicitly declare several equally named methods 
within a class.
This is termed {\it overloading} of methods.
Overloaded methods must differ in the number of their parameters.%
\footnote{This restriction has been made to avoid ambiguities. 
          For illustration consider the following case:

{\tt \begin{tabbing}
\hspace{10mm}\=class A \{ ... \};\hspace{2cm}\=\kill
\>class A \{ ... \};\>class C\\
\>                  \>\{~~~~~void~~~m (A);\\
\>class B \{ ... \};\>~~~~~~void~~~m (B);~~~~\};
\end{tabbing}}

If later a class declaration: {\tt D: A,B} is
made, then a call of method {\tt m} with an instance
of class {\tt D} given as argument can not be resolved
without ambiguity.}
Static methods may only be overloaded by other static methods but
not by non-static methods.

If an expression is specified in a parameter-list this expression is
used as a default argument.
All subsequent parameters must also have default arguments.
A declaration of a method
\[ f(p_1,\dots,p_n,p_{n+1} = d_1,\dots,p_{n+m} = d_m) \]
with default arguments {\tt $d_1,\dots,d_m$} stands for the following
set of overloaded methods:%
\footnote{Note, that according to the above rule for overloading, a
          method with default arguments cannot be
          overloaded with a method which has the same number of
          arguments as any method in that set, i.e. the method sets
          associated with overloaded methods must not contain two
          methods with the same number of parameters.}
\[\{ f(p_1,\dots,p_{n+i}) \;|\; 0 \leq i \leq m \} \]
A call
\[ f(a_1,\dots,a_{n+i}), \; 0 \leq i \leq m \]
of such a method is mapped to
\[ f(a_1,\dots,a_{n+i},d_{i+1},\dots,d_m), \; 0 \leq i \leq m \]
i.e. default arguments are used when trailing arguments are missing.

Some function methods are implicitly declared, as for
example methods to create instances of a class or methods to compare instances. 
They are described in detail in 
Section~\ref{sec:Predefined Methods}.

\pagebreak[3]
%-------------
\subsubsection{Names and Expressions}
\label{sec:Names and Expressions}

\begin{Grammar}
\>expression ::=
  name $|$ number
       $|$ name {\bf (} [ expression // {\bf ,} ] {\bf )}\\
\end{Grammar}

An expression can be a name, number, or a function call.
It is only syntactically checked; its interpretation is left to the host
languages.

The special names {\tt NO\_OBJECT}, {\tt TEMP\_CONTAINER},
and {\tt ROOT\_CONTAINER} are available. The name
{\tt NO\_OBJECT} denotes an object reference which
does not reference any existing object.
No methods except comparing object identities may be applied to
{\tt NO\_OBJECT}. 
The meanings of the names {\tt TEMP\_CONTAINER}
and {\tt ROOT\_CONTAINER} are explained in
Section~\ref{sec:The Type sos_Container}.

\pagebreak[3]
%-------------
\subsubsection{Derived Classes}
\label{sec:Derived Classes}

A class may be {\it derived} from one or more other classes (called
{\it superclasses} of the derived class).
If a class is (directly) derived from several other classes,
this is called {\it multiple inheritance}.
A derived class inherits non-static methods that are declared in
its (direct and indirect) superclasses.
Thus, all the inherited methods, except private methods, are
accessible by an instance of the subclass. 
Protected methods remain protected, and public ones remain public.

A class may only be derived from classes that have been defined
(textually) before.
If no superclass is specified for a class, the class is implicitly
derived from the root class {\tt sos\_Object}
(see Section~\ref{sec:The SOS Environment}).%

{\bf Example:}

Two classes, {\tt Student} and {\tt Instructor} may be derived
from class {\tt Person}:
\begin{verbatim}
class Person { ... };

class Course
{
public:
      sos_String  topic;
      Instructor  instructor;
};
\end{verbatim}
\pagebreak[3]
\begin{verbatim}
class Instructor : Person             class Student : Person
{                                     {
public:                               public:
      sos_Int  salary;                      Set<Course>  courses;
      Course   course;                };
};
\end{verbatim}

where {\tt Set<Course>} is a generic instantiation of the standard
generic class {\tt Set} (see Section~\ref{sec:Generic Class Types}).
Note the implicit declaration of class {\tt Instructor} within the
body of class {\tt Course}.

Multiple inheritance can be demonstrated by a class which describes
students who also work as technical assistants.

\begin{verbatim}
class Assistant : Student, Instructor
{    
public:
      Instructor  associated_professor;
};
\end{verbatim}

$\Box$

% 29.10.91mr
Note, that superclasses are the classes mentioned 
in the ``super-classes'' list and, transitively,
the superclasses of superclasses.
% end 29.10.91mr
A {\it direct superclass} {\tt D} of class {\tt A} is a superclass
of {\tt A}, such that no other superclass {\tt B} of {\tt A}
exists of which {\tt D} also is a superclass.
The specification of indirect superclasses 
in the ``super-classes'' list is merely redundant with
respect to inheritance.%
\footnote{The naming of indirect superclasses might be necessary for
          the specification of its class initialization as described
          in Section~\ref{sec:Object Creation}.}

Inheritance in SOS is {\it transitive} which means that a class that
is directly or indirectly derived from one or more other classes owns
the interfaces of all these superclasses, i.e. the method interface
of a class is made up of all methods declared in its own declaration
or in the declaration of one of its superclasses.
Furthermore, inheritance is indirect or ``virtual'' as e.g. the
C++ language reference manual calls it. 
That means, each component exists only once even if it is inherited
along multiple paths in the inheritance lattice.

A method implementation is associated with each method belonging to
the method interface of a class.
For methods that are a part of the interface of a direct superclass,
that association is inherited as a default, too.
An association may also be changed by providing a different method
implementation in a subclass; this is termed {\it redefinition}
of that method.
A method is redefined by declaring it explicitly in the subclass
declaration.
That declaration must match the original declaration exactly with 
the following exceptions:
abstract methods may be declared as non-abstract and the redefined
method may have extended access rights, i.e. a protected method may
be redefined as public.
Furthermore, default arguments
(see Section~\ref{sec:Function Methods}) may be changed in a
subclass and additional default parameters may be introduced:
either by providing a default argument for previously non-default
parameters, or by adding parameters with default arguments.%
\footnote{Note, that these two possibilities may also be
          formulated using the method sets introduced in
          Section~\ref{sec:Function Methods} by requiring that the
          method set associated to the redefinition is a superset
          of the method set associated to the method in the
          superclass.}
Components can be ``redefined'' in a restricted sense by redefining
the corresponding {\tt get} and {\tt set} methods.

As already mentioned
(see Section~\ref{sec:Function Methods}),
methods of a class are always virtual.
This means that the actual method that is applied to a given object
is identified by the actual type of this object.
This rule avoids the requirement on host languages to provide static
typing, which is needed for the identification of non-virtual
methods through a type that is associated to a variable at compile
time.

Besides redefining a method it is also possible to overload an
inherited method in a derived class.
This case is handled according to the rules listed in
Section~\ref{sec:Function Methods}, which state that overloading
of a method is only admissible if the overloaded methods differ
sufficiently:
the method declared in the derived class must be non-static and it
must not be possible to call the methods with the same number of
arguments, i.e. the number of (default and non-default) parameters of
one method must be smaller than the number of non-default parameters
of the other method.

An intrinsic problem all systems providing multiple inheritance have
to deal with is the problem of name clashes.
This occurs when equally named methods belong to the method
interfaces of different direct superclasses.
Three cases can be distinguished:
\begin{itemize}
\item The methods have identical signatures and are all associated
      to the same implementation. 
      This is the case when they all originate from a single
      explicit definition, i.e. the method is inherited by the 
      direct superclasses from a single (indirect) superclass without
      any redefinitions. In the derived class this definition 
      (i.e. method declaration and the associated implementation) 
      is then inherited, too.
\item The number of actual parameters differs in each possible call
      of the methods, i.e. the number of (default and non-default)
      parameters of one method is smaller than the number of
      non-default parameters of the other method.
      In this case the method declarations as well as their
      associated implementations are inherited as described above.
      Those inherited methods are handled as overloaded methods
      (see Section~\ref{sec:Function Methods}).
\item The methods are associated to different implementations and may
      be called with the same number of arguments.
      In this case they must both be redefined by a single method
      in the derived class and are therefore not inherited.%
      \footnote{This forced redefinition avoids a dependency on the
                inheritance strategy of a host language; the language
                Flavors, for example, specifies inheritance with
                respect to an ordering of the superclasses.}

      According to the rules stated above, a redefinition is not
      admissible if the methods to be redefined differ e.g. in the
      types of at least one parameter or in the result type, since
      there can be no single method which redefines those differing
      methods simultaneously.
      Hence, it is not possible to inherit from superclasses
      containing methods which are incompatible in the above sense.%
      \footnote{To cope with that problem a mechanism like
                ``renaming'' as offered for e.g. by the Eiffel
                language (\cite{Meye88}) would be needed.
                No such mechanism is yet provided in the SOS
                language.}
     Therefore, SOS class designers are admonished to be careful
     when choosing method signatures in order to avoid such a
     conflict when their class is used as a superclass.
\end{itemize}
Some examples are given to illustrate what kind of redefinitions 
are allowed and when they are necessary in the SOS data model:
\begin{verbatim}
class A
{    
public:
   A  f1 (A); 
};

class B : A                        class C : A
{                                  {
public:                            public:
   A  att;                            A  f2 (A, B=def1);    
   A  g1 (A);                         A  g1 (A);
   A  g2 (A);                         A  g2 (A, B);
};                                 };


class D : B, C
{    
public:
   A  g1 (A);                 // forced redefinition!
   A  f1 (A);                 // unforced redefinition
   A  get_att();              // unforced redefinition of a component
                              // access method 
   A  f2 (A, B=def3, C=def4); // unforced redefinition with different
                              // and more default arguments
   A  g2 (A, B, C);           // overloading of g2(A) and g2(A,B)
};
\end{verbatim}

$\Box$

%-------------
\subsubsection{Generic Class Types}
\label{sec:Generic Class Types}

\begin{Grammar}
\>generic-parameter-specification ::=\\
\>\>{\it type-}name [ {\bf :} {\it superclass-}type-name ]\\
\\
\>generic-instantiation ::=\\
\>\>{\it generic-class-}name
    $\bf <$ (type-name // {\bf ,}) $\bf >$
\end{Grammar}

Class declarations that contain generic parameters are called
{\it generic classes}.
The generic parameters denote formal types; they may be used as type
names within the class declaration but not in another
``generic-parameter-specification''.
A ``generic-parameter-specification'' may optionally contain a type
name that specifies
% 29.10.91mr
the actual parameter to be this type or a subclass thereof.%
\footnote{This concept is sometimes called {\it constrained genericity}
          (see e.g. \cite{Meye88})};
By default, {\tt sos\_Object} is taken as this type name.
% end 29.10.91mr
Additionally, scalar types may be used as actual parameters, provided
the class {\tt sos\_Scalar\_object}
(see Section~\ref{sec:The Scalar Types})
is an admissible actual parameter type.

With the declaration of a generic class one instantiation of that
class is always implicitly declared, too.
For this implicitly declared class, the
generic type names are replaced by the stated 
{\it superclass-}type-names.
This is the class for which the schema implementor has to implement
the function methods specified for the generic class.
Therefore, in this implementation the
properties of the superclass may be assumed
(in particular, for statically typed languages).

\pagebreak[4]
{\bf Example:}

The example declares a type {\tt Ordered\_list}, where the element
type is assumed to be an {\tt Ordered\_object}, having an ordering
relation as method.
Furthermore, an instantiation of the generic class
{\tt Ordered\_list} is shown where the formal parameter {\tt Entity}
is replaced by a subclass of {\tt Ordered\_object}.

\begin{verbatim}
class Ordered_object
{
public:
   sos_Bool operator<= (Ordered_object);
};

class Ordered_list <Entity : Ordered_object> : List <Entity>
{
public:
   void insert (Entity); // implementation based on operator<= of Entity
};
\end{verbatim}
\pagebreak[3]
\begin{verbatim}
class Phone_book_entry : Ordered_object, Person
{  
public:
   sos_Int  phone_no;
                         // alphabetic ordering based on person names
   sos_Bool operator<= (Ordered_object);
};

typedef Ordered_list<Phone_book_entry> Phone_book;
\end{verbatim}

$\Box$

Several generic types are predefined, like {\tt Set}, {\tt List},
or {\tt Array}.
Their methods will be introduced in Appendix~\ref{sec:Manual Pages}.

A {\it generic instantiation} generates an ordinary class from a
generic class by providing actual types for the generic parameters.
The actual types are restricted to classes derived from the superclass
given in the ``generic-parameter-specification'' of
the corresponding formal generic parameter (which is
{\tt sos\_Object} by default).
The generated class has the generic parameters replaced by the actual
types.
All methods of the generic instantiation are implicitly implemented
by calling the corresponding methods of the generic class, and
performing the appropriate type conversions (in particular, for
statically typed languages).

It is necessary to declare generic instantiations if they shall be
available at the programming interface.
Explicit declaration by using the {\tt typedef} construct
(see Section~\ref{sec:Type Declarations}) is only
necessary if there is no implicit declaration of this specific
instantiation, by any other use of the ``generic-instantiation''
construct.

{\bf Example:}

Generic classes can be used to define arbitrary type constructors
like {\tt Set}, {\tt Bag}, {\tt List}, {\tt Array}, and
{\tt Mapping}.
The declaration below shows the generic class {\tt Set}.
Instances of the generic class are declared by providing actual
types for the generic parameter of {\tt Set} in the class
{\tt Unix\_Directory}.

\begin{verbatim}
class Set<Entity>
{
   sos_Int  cardinality;
   ...
public:
   sos_Bool     is_element (Entity);
   void         insert (Entity);
   void         remove (Entity);
   Set<Entity>  operator* (Set<Entity>); // intersection
   Set<Entity>  operator+ (Set<Entity>); // union
   Set<Entity>  operator- (Set<Entity>); // difference
   ...
};
\end{verbatim}
\pagebreak[3]
\begin{verbatim}
class Unix_directory
{
   Set<File>            files;
   Set<Unix_directory>  sub_directories;
public:
   sos_Bool     rm    (Set<File>);
   sos_Bool     rmdir (Set<Unix_directory>);
   sos_Bool     mv    (Set<File> fs, Unix_directory to_dir);
   ...
};
\end{verbatim}

$\Box$

%----------
\subsubsection{Predefined Function Methods}
\label{sec:Predefined Methods}

Several function methods are predefined for each class.
Some of those methods are defined in the root class {\tt sos\_Object}
and propagated through the inheritance mechanism.
These function methods are described in
Section~\ref{sec:The SOS Environment}.

Some other function methods explained below are generated for a
class by the interface builder of a programming language.
These comprise object creation and destruction, asserting the type
of an object, copying and assigning objects, comparing objects, and
component methods.

Unless stated below it is an error to declare one of these implicitly
declared methods explicitly in an SOS schema.
Most of the generated functions are based on static methods defining
a class local behavior.
The names of these methods start with the prefix {\tt total} or
{\tt local}.
These methods can be defined explicitly in order to provide a user
defined implementation.
The explicitly declared method must have exactly the same signature
as the one shown in the sequel and must allow at least a
protected access.
This applies to all methods with an equal name, i.e. it is also not
allowed to ``overload'' the {\tt total\_} / {\tt local\_} methods
-- even if those methods are actually not defined for a class.

%-------------
\paragraph{Object Creation and Initialization}\hfill\\
\label{sec:Object Creation}

An instance of a class {\tt C} defined in an SOS schema is created
by a call of the static function {\tt create} of this class:
\begin{verbatim}
   static C  create (sos_Container, ...);
\end{verbatim}
Such a function method is generated for each non-abstract class, i.e.
each class containing no abstract methods.
The {\tt create} function allocates space for the new object in the
given container and initializes the new object.

The signature of this function is defined in the declaration of its
class by listing the {\it create parameters} after the class name
(see~\ref{sec:Class Types}).
An empty list of create parameters may be omitted.

The container where an object is to be placed is always the first
parameter of {\tt create}.
This parameter must not be mentioned in the create parameter list
of the class declaration; it is implicitly inserted.
This means that no reference to this parameter within an
initialization expression (see below) is possible, and that it 
is not possible to specify any default argument for this parameter.

The initialization of components is done by setting value components
to the predefined value {\tt NO\_OBJECT}
(see Section~\ref{sec:Names and Expressions}),
and by assigning the initialization
expressions to the corresponding components (init-components)
as described in Section~\ref{sec:Components and Component Methods}.
No assumptions can be made about the value of the remaining 
components if no explicit initialization is provided in a
{\tt local\_initialize} method.

An initialization expression is an expression (see 
Section~\ref{sec:Names and Expressions}) in which
it is possible to refer to create parameters.
Initialization expressions are evaluated in an undefined order.
A somewhat more sophisticated initialization can be done classwise
within a function method:

\pagebreak[4]
\begin{verbatim}
class C
{ ...
protected:
   static void  local_initialize (C);
}
\end{verbatim}
If such a method is declared, it is used by the {\tt create}
operation of the class {\tt C} and by the {\tt create} operations
of all subclasses of {\tt C}. 
Initialized components may be used in a {\tt local\_initialize} 
method because all initialization expressions are evaluated before
any {\tt local\_initialize} method is called.
The initialization methods of a class and its superclasses will be
executed in some order for which the {\tt local\_initialize} 
method of a
superclass is called before the {\tt local\_initialize} method of 
any of its
derived classes.%
\footnote{It is strongly recommended to ensure that the type of a
          value component set during {\tt local\_initialize} does
          solely depend on the values of init-components.
          Otherwise, the {\tt clone} function method might fail (see
          Section~\ref{sec:Copying Objects}).}

In order to initialize the init-components belonging to superclasses
a mapping must be provided from the create parameters of a class to
the create parameters of its superclasses.
This is termed {\it class-initialization} in the productions shown in
Section~\ref{sec:Class Types}.
A class initialization is specified by appending a parameter list to
the name of a superclass.
The create parameters of the superclass defined that way are used to
initialize the init-components belonging to the superclass and to
derive definitions for create parameters of further superclasses,
according to the declaration of the superclass.

Thus, the initialization of a class and its superclasses can be
formulated in a recursive manner by giving in each class just the
initializations for its direct superclasses.

However, it is also possible to specify explicitly the create parameters
for an indirect superclass.
As explained at the end of Section~\ref{sec:Derived Classes} the
specification of an indirect superclass is redundant with respect to
inheritance.
However, those redundant specifications may be used
to declare a non-recursive class initialization by explicitly stating
the initialization for an indirect superclass in the
``super-classes'' list.
Again, those specifications are used to derive initializations for
further superclasses unless the initialization of a superclass is
stated in the ``super-classes'' list.

An explicit class initialization must be used in case alternative
superclass initializations derived along different paths in the
inheritance lattice are not equivalent.

{\bf Example:}

The following class declarations show a typical example for
the use of create parameters:

\pagebreak[4]
\begin{verbatim}
class Aggregate (sos_Bool based_on_equal)
{  // implicitly declared create-function:
   // static Aggregate::create (sos_Container ...,
   //                           sos_Bool based_on_equal);
   //    allocate space for the Aggregate object,
   //    initialize the component boq,
   //    and then call function Aggregate::local_initialize

   private:
      sos_Bool boq = based_on_equal;
   ...

   protected:
      static void local_initialize (Aggregate);
   ...
};


class Array<Entity> (sos_Bool based_on_equal, sos_Int lb, sos_Int ub)
     : Aggregate (based_on_equal)
{  // implicitly declared create-function:
   // static Array::create(sos_Container ...,
   //                      sos_Bool based_on_equal,
   //                      sos_Int lb, sos_Int ub);
   //    allocate space for the Array object,
   //    initialize init-components in classes Aggregate and Array,
   //    and then call functions 
   //           Aggregate::local_initialize
   //      and  Array::local_initialize

   private:
      sos_Int lower_bound = lb;
      sos_Int upper_bound = ub;
   ...
   protected:
      static void local_initialize (Array<Entity>);
   ...
};


class Array_1<Entity> (sos_Bool based_on_equal, sos_Int ub)
     : Array (based_on_equal, 1, ub)
{  // implicitly declared create-function:
   // static Array_1::create (sos_Container ...,
   //                         sos_Bool based_on_equal, sos_Int ub);
   //    allocate space for the Array_1 object,
   //    initialize init-components in classes Aggregate and Array,
   //    and then call the functions 
   //         Aggregate::local_initialize
   //    and  Array::local_initialize
   //    there are no init-components and no local_initialize method
   //    declared in this class!
   ...
};
\end{verbatim}

$\Box$

%---------
\pagebreak[3]
\paragraph{Object Destruction}\hfill\\

Similar to object creation a function method is provided to destroy
an object, i.e. to deallocate the space occupied by that object and
to recursively destroy its value components:
\begin{verbatim}
   void  destroy();
\end{verbatim}
The destruction of an object might require explicit actions which
mirror the corresponding {\tt local\_initialize} methods.
Therefore, such function methods can be declared analogously by
declaring a method with the following signature:
\begin{verbatim}
class C
{ ...
protected:
   static void local_finalize (C);
}
\end{verbatim}
These {\tt local\_finalize} methods are called before the 
{\tt destroy}
operations for the value components of {\tt C}.
They are called in an order for which a {\tt local\_finalize} 
method of a superclass is called after the {\tt local\_finalize}
methods of its subclasses.

%---------
\paragraph{Asserting the type of an object}\hfill~\\

The static function method
\begin{verbatim}
   static C  make (sos_Object);
\end{verbatim}
asserts that the type of the parameter object actually is {\tt C} or
one of its subtypes.
Furthermore, in a statically typed language {\tt make} yields a reference
to the given object typecasted to the static type {\tt C}.

%---------
\paragraph{Assigning Objects}\hfill\\
\label{sec:Assigning Objects}

The non-static member function
\begin{verbatim}
   void  assign (sos_Object source);
\end{verbatim}
assigns {\tt source} to the target object it is applied to by
setting the values of the components in the target object to the 
values of the corresponding components of {\tt source}. 
{\tt source} must belong to the class of the target object or a
subclass of this class; 
this applies recursively to corresponding value components, too.

Each class with at least one component has a static 
function method
\begin{verbatim}
protected:
   static void  local_assign (C dest, sos_Object source);
\end{verbatim}
which performs the assignment of the components belonging to class
{\tt C}.
This includes recursive invocations of {\tt assign} methods for the
value components of class {\tt C}.

The generated total {\tt assign} method is spliced together by
calling the {\tt local\_assign} methods for a class and its
superclasses (if such a method exists) in an order for which the
{\tt local\_assign} method of a class is executed after the
{\tt local\_assign} methods of its superclasses.

The generated {\tt assign} method may be modified in two ways.
One consists in explicitly declaring the function
{\tt local\_assign} with exactly the mentioned signature.
In that case no implementation of that method is generated and an
implementation has to be provided by the schema implementor. 
If it is furthermore not desired that calls of {\tt local\_assign}
methods of superclasses are generated, a method with the following
signature may be declared for a class {\tt C}:
\begin{verbatim}
protected:
   static void  total_assign (C dest, sos_Object source);
\end{verbatim}
This method replaces all calls of assignment methods%
\footnote{This includes {\tt local\_assign} methods as well as 
          other {\tt total\_assign} methods.}
defined for superclasses of class {\tt C} in the generated 
{\tt assign} methods for class {\tt C} and all subclasses of 
this class.
%
%The above rule for the generation of the {\tt assign} method for a
%class {\tt C} has to be extended to account for {\tt total\_assign}
%methods.
%{\tt assign} consists of calls:
%\begin{itemize}
%\item of the {\tt total\_assign} methods of those superclasses
%      {\tt A} of {\tt C} (including the case {\tt A == C}) for which
%      a {\tt total\_assign} method is declared, if the assignment 
%      of the components belonging to {\tt A} and its superclasses is
%      not already performed by a call of another {\tt total\_assign}
%      method
%      (this another {\tt total\_assign} method must then
%       belong to a class {\tt B} which is both a superclass of
%       {\tt C} ({\tt B} may equal {\tt C}) and a (proper) subclass of
%       {\tt A}).
%\item of the {\tt local\_assign} methods of {\tt C} and its
%      superclasses if such a method exists for a class and the
%      components belonging to the class are not already assigned by
%      a call of a {\tt total\_assign} method.
%      The {\tt local\_assign} methods are called after the
%      {\tt total\_assign} methods in an order for which the
%      {\tt local\_assign} method of a class is executed after the
%      {\tt local\_assign} methods of its superclasses.
%\end{itemize}

Due to conflicting {\tt total\_assign} methods the generation of an
{\tt assign} method may be erroneous for a class {\tt C} if the following
conditions hold:
\begin{itemize}
\item
There are two superclasses {\tt A} and {\tt B}
of {\tt C} with explicitly defined
{\tt total\_assign} methods, and
\item
the intersection of the sets of superclasses of {\tt A}
and {\tt B} is neither identical with one of the
superclass sets nor identical with the set
{\tt \{sos\_Object\}}.
\end{itemize}
In that case a {\tt total\_assign} method should be defined explicitly
for {\tt C}.%
%Therefore, schema implementors must be aware that the use of
%{\tt total\_assign} methods may render it impossible to
%automatically generate an {\tt assign} method for subclasses.%
\footnote{Note, that the declaration of {\tt total\_assign} methods
          is only intended to be an expedient and should really
          seldom be necessary.}

The following example illustrates how the {\tt assign} method 
of a class is generated, depending on the {\tt total\_assign} and
{\tt local\_assign} methods defined for 
its superclasses.
The example is quite complex, because it is intended to
cover most of the difficult cases a user may
be confronted with, when redefining assign operations.

{\bf Example:}

In the following class hierarchy, class names have a suffix that
indicates whether a {\tt total\_assign} method is provided,
or if only a {\tt local\_assign} is available.

\begin{figure}[hbt]
\begin{center}
\
\vspace*{7.5mm}
\psfig{figure=figures/local-total.epsi,height=8cm,width=10.5cm}
\vspace*{7.5mm}
\end{center}
\end{figure}

The generated {\tt assign} methods for these classes are outlined 
below.\footnote{For brevity C++ syntax is used}
{\samepage
\begin{verbatim}
   void A::assign (sos_Object o) { A::local_assign (self, o); }
   void B::assign (sos_Object o) { B::local_assign (self, o); }
   void C::assign (sos_Object o) { A::local_assign (self, o);
                                   C::local_assign (self, o); }
   void D::assign (sos_Object o) { D::total_assign (self, o); }
   void E::assign (sos_Object o) { E::total_assign (self, o); }
   void F::assign (sos_Object o) { C::local_assign (self, o);
                                   D::total_assign (self, o);
                                   F::local_assign (self, o); }
   void G::assign (sos_Object o) { G::total_assign (self, o); }
   void H::assign (sos_Object o) { F::local_assign (self, o);
                                   C::local_assign (self, o);
                                   D::total_assign (self, o);
                                   G::total_assign (self, o); 
                                   H::local_assign (self, o); }
\end{verbatim}
}
Note, that {\tt A::local\_assign} is not called in
{\tt F::assign}, because this method is already covered by 
{\tt D::total\_assign}.

If class {\tt H} in this example would
inherit additionally from class {\tt E} the
rule given above would be fulfilled and the following 
{\tt assign} method for this class would be generated:
\begin{verbatim}
   void H::assign (sos_Object o) { F::local_assign (self, o);
                                   E::total_assign (self, o);
                                   D::total_assign (self, o);
                                   G::total_assign (self, o); 
                                   H::local_assign (self, o); }
\end{verbatim}
Note, that without defining a {\tt total\_assign} method in class {\tt H}
the  {\tt total\_assign} methods of the classes {\tt E} and {\tt D}
are both called.
For both classes have class {\tt A} as a superclass,
there might occur difficulties, due to the two times assignment
of this class.

%---------
\paragraph{Copying Objects}\hfill\\
\label{sec:Copying Objects}

The basic operation to copy an object is the static function
method
\begin{verbatim}
   static C  clone (C source, sos_Container ct);
\end{verbatim}
which yields a copy of the object {\tt source} in the given container
{\tt ct}.
The value components are copied, too.
The type of the new object is the same as the type of the 
{\tt source} object (which maybe {\tt C} or any type derived from {\tt C}).

The copying may be thought of as an succession of {\tt create} and
{\tt assign} with the exception that no create parameters are needed.
Instead, after allocating space for the new object its
init-components are initialized by copying the corresponding
components of the source object.
Afterwards, the {\tt local\_initialize} methods are called on the 
new object as described in Section~\ref{sec:Object Creation}.
The clone is completed by assigning the source object to the new
object.

{\tt assign} will fail if a source object does belong to a superclass
of the class of the corresponding target object.%
\footnote{Therefore, it is mandatory that in a {\tt local\_initialize}
          method no value components are set whose type does not
          solely depend on the values of init-components.
          Otherwise, {\tt clone} may fail unexpectedly due to a
          failing {\tt assign} method called recursively for a
          value component.}

In contrast to {\tt clone}, the static function method
\begin{verbatim}
   static C  copy (C source, sos_Container ct);
\end{verbatim}
yields a copy of {\tt source} as an object of class {\tt C}, i.e.
only the components belonging to {\tt C} or its superclasses are
copied.
It is very important to note the difference between the two ways
to copy an object: The function method {\tt clone} yields an instance
belonging to the class of the source object while the function
method {\tt copy} yields an instance of the class to which
the static {\tt copy} method belongs.

%---------
\paragraph{Comparing Objects}\hfill\\
\label{sec:Comparing Objects}

As stated in Section~\ref{sec:Components and Component Methods}
two SOS objects are {\it equal} if they have the same value and type.
Depending on whether a component of an object is a {\it value
component} (see Section~\ref{sec:Components and Component Methods})
or not, the value of that object is made up from the value or the
identity of this component, respectively.
That comparison is performed by the non-static function method
\begin{verbatim}
   sos_Bool  equal (sos_Object o, sos_Eq_kind eq_kind=EQ_STRONG)
\end{verbatim}
which yields {\tt TRUE} if the object it is applied to has the same
value as the object {\tt o}.
This requires that both objects belong to the same class.
Optionally, the comparison may be done for a weaker form of equality:
{\tt o1.equal(o2,EQ\_WEAK)} yields {\tt TRUE} if
the following three conditions hold:
\begin{itemize}
\item
{\tt o1} belongs to the same class or a superclass of {\tt o2}'s
class and
\item
all value components of {\tt o1} are {\tt equal(...,EQ\_WEAK)}
to the corresponding value components of {\tt o2} and
\item
all non-value components of {\tt o1} are identical to
their counterparts in {\tt o2}.
\end{itemize}
Note, that strong equality differs in the first two conditions:
{\tt o1} must belong to the same class as {\tt o2}, and value
components are also compared for strong equality.

As in the case of the {\tt assign} method described in
Section~\ref{sec:Assigning Objects} the behavior of the 
{\tt equal} method can be changed on
two levels first by explicitly defining a class local comparison done
in the static function method
\begin{verbatim}
class C
{ ...
protected:
   static sos_Bool  local_equal (C o1, sos_Object o2,
                                 sos_Eq_kind eq_kind);
}
\end{verbatim}
and secondly by explicitly defining a 
{\tt total\_equal} method:
\begin{verbatim}
class C
{ ...
protected:
   static sos_Bool  total_equal (C o1, sos_Object o2,
                                 sos_Eq_kind eq_kind);
}
\end{verbatim}
The rules stated in the preceding section for {\tt total\_assign} and
{\tt local\_assign} apply analogously to {\tt total\_equal} and
{\tt local\_equal}.
When redefining the comparison operation, regard should be paid that
{\tt equal} with {\tt eq\_kind == EQ\_STRONG} should be an equivalence relation.

%---------
\paragraph{Mapping Objects to Integers}\hfill\\

For all objects a function is provided that computes an integer
value from the value of the object.
\begin{verbatim}
   sos_Int  hash_value();
\end{verbatim}
It is intended to have a very low possibility for objects that are
not equal to return the same value.
Equal objects must always return the same hash value.
Therefore, it is often appropriate to redefine this function when
the {\tt equal} method is to be redefined.

Analogously to the two preceding sections the global
{\tt hash\_value} function is constructed from class local hash
functions
\begin{verbatim}
protected:
   static sos_Int  local_hash_value (C);
\end{verbatim}
and as well the {\tt local\_hash\_value} method as the 
{\tt total\_hash\_value}
functions can be defined by a schema implementor.

%---------
\pagebreak[4]
\paragraph{Component Methods}\hfill\\

According to the description of
Section~\ref{sec:Components and Component Methods} for each component
\begin{verbatim}
   T c;
\end{verbatim}
two non-static function methods are generated
\begin{verbatim}
   void set_c (T);
   T    get_c ();
\end{verbatim}
which set and get the corresponding component value of an object.
{\tt c} will hold the identity of the given object, the {\tt get\_c}
operation yields this identity.

The {\tt set\_c} method includes additional checks if {\tt c} is
either a local or a value component.
In both cases only objects within the same container as the object
to which {\tt c} belongs may be given as arguments.
In case of a value component {\tt set\_c} may be called only once to
establish the connection between a value component and its master
object.

The {\tt get} and {\tt set} methods can be handled as any other
function method, i.e. they can for example be redefined in a subclass
if the component is not declared to be {\tt definite}.
It is also possible to declare {\tt get\_c} (respectively {\tt set\_c})
explicitly in the class to which {\tt c} belongs.
In this case the predefined methods are generated with the names
{\tt \_get\_c} (respectively {\tt \_set\_c}) in order to enable the
access to the value of the component {\tt c}.

The declaration of a component {\tt T c} may also be used to redefine
inherited function methods {\tt set\_c(T)} and/or
{\tt T get\_c()}.

%----------
\pagebreak
\subsection{Example for a Schema Interface}

\begin{verbatim}
with agg;
schema Documents
{      
   class Document : sos_Named
   {      
   public:
       sos_String  name;
       Set<Person> authors;
       Person      owner;
      !Date        creation_date, last_modification;
   };
};

with Grammars;
schema Texts
{      
   class Text
   {
   public:
      void edit ();
   };

   class Formal_text : Text
   {
   public:
      void parse (Text, Grammar);       // parser
      void edit ();                     // structure oriented editor
      Text flatten (Grammar);           // unparser
   };
};

with Executables;
schema Code_modules
{      
   class Code_module { ... };

   class Executable_code : Executable
   {
   public:
      void exec ();
   };
\end{verbatim}
\pagebreak
\begin{verbatim}
   class Code_module_set : Set<Code_module>
   {
   public:
      Executable_code link ();
   };
};

with Documents, Texts, Code_modules;
schema Software_libraries
{  
   class Requirement_definition : Text, Document { ... };

   class Program : Formal_text, Document
   {
   public:
      Code_module compile ();
   };

   class Specification : Formal_text, Document
   {
   public:
      Program synthesize ();
   };

   class Library
   {
   public:
      Set<Requirement_definition>       requirement_definitions;
      Set<Specification>                specifications;
      Set<Program>                      programs;
      Mapping<Program,Specification>    implements;
   };
};

with Documents;
schema Unix_Directories
{  
   class Unix_Directory : Document
   {
   public:
      Set<Document> documents;
   };
};
\end{verbatim}

